/*
 * Copyright (C) 2011, EADS France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

package xowl.interpreter.backends.jena;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Laurent WOUTERS
 */
public class JenaQueryVariableEvaluator implements xowl.interpreter.impl.Evaluator {
    private JenaRepository repository;
    private Map<xowl.lang.actions.QueryVariable, com.hp.hpl.jena.graph.Node> variables;
    private com.hp.hpl.jena.reasoner.rulesys.RuleContext context;
    private Map<xowl.lang.actions.QueryVariable, xowl.lang.runtime.Value> mapValues;

    public JenaQueryVariableEvaluator(JenaRepository repository, Map<xowl.lang.actions.QueryVariable, com.hp.hpl.jena.graph.Node> vars, com.hp.hpl.jena.reasoner.rulesys.RuleContext context) {
        this.repository = repository;
        this.variables = vars;
        this.context = context;
        this.mapValues = new HashMap<xowl.lang.actions.QueryVariable, xowl.lang.runtime.Value>();
    }

    @Override public boolean can(xowl.lang.owl2.Expression exp) {
        if (!(exp instanceof xowl.lang.actions.QueryVariable))
            return false;
        return variables.containsKey((xowl.lang.actions.QueryVariable)exp);
    }
    @Override public boolean can(xowl.lang.actions.Query exp) { return false; }


    private xowl.lang.runtime.Value eval_QueryVariable(xowl.lang.actions.QueryVariable expression) throws xowl.interpreter.XOWLException {
        if (mapValues.containsKey(expression))
            return mapValues.get(expression);
        xowl.lang.runtime.Value value = valueOf(variables.get(expression), context);
        mapValues.put(expression, value);
        return value;
    }
    private xowl.lang.runtime.Value valueOf(com.hp.hpl.jena.graph.Node varNode, com.hp.hpl.jena.reasoner.rulesys.RuleContext rc) throws xowl.interpreter.XOWLException {
        com.hp.hpl.jena.graph.Node gv = rc.getEnv().getGroundVersion(varNode);
        com.hp.hpl.jena.rdf.model.RDFNode jenaNode = repository.getJenaModel().asRDFNode(gv);
        xowl.interpreter.backends.rdf.RDFNode xowlNode = repository.getRDFNode(jenaNode);
        return repository.getValue(xowlNode);
    }

    @Override public xowl.lang.runtime.Value evaluate(xowl.interpreter.impl.Evaluator parent, xowl.lang.owl2.Expression expression) throws xowl.interpreter.XOWLException { return eval_QueryVariable((xowl.lang.actions.QueryVariable)expression); }
    @Override public xowl.lang.runtime.Entity evalEntity(xowl.interpreter.impl.Evaluator parent, xowl.lang.owl2.EntityExpression expression) throws xowl.interpreter.XOWLException { return parent.toEntity(eval_QueryVariable((xowl.lang.actions.QueryVariable)expression)); }
    @Override public xowl.lang.runtime.Class evalClass(xowl.interpreter.impl.Evaluator parent, xowl.lang.owl2.ClassExpression expression) throws xowl.interpreter.XOWLException { return parent.toClass(eval_QueryVariable((xowl.lang.actions.QueryVariable)expression)); }
    @Override public xowl.lang.runtime.ObjectProperty evalObjProp(xowl.interpreter.impl.Evaluator parent, xowl.lang.owl2.ObjectPropertyExpression expression) throws xowl.interpreter.XOWLException { return parent.toObjProp(eval_QueryVariable((xowl.lang.actions.QueryVariable)expression)); }
    @Override public xowl.lang.runtime.DataProperty evalDataProp(xowl.interpreter.impl.Evaluator parent, xowl.lang.owl2.DataPropertyExpression expression) throws xowl.interpreter.XOWLException { return parent.toDataProp(eval_QueryVariable((xowl.lang.actions.QueryVariable)expression)); }
    @Override public xowl.lang.runtime.Datatype evalDatatype(xowl.interpreter.impl.Evaluator parent, xowl.lang.owl2.Datarange expression) throws xowl.interpreter.XOWLException { return parent.toDatatype(eval_QueryVariable((xowl.lang.actions.QueryVariable)expression)); }
    @Override public xowl.lang.runtime.Individual evalIndividual(xowl.interpreter.impl.Evaluator parent, xowl.lang.owl2.IndividualExpression expression) throws xowl.interpreter.XOWLException { return parent.toIndividual(eval_QueryVariable((xowl.lang.actions.QueryVariable)expression)); }
    @Override public xowl.lang.runtime.Literal evalLiteral(xowl.interpreter.impl.Evaluator parent, xowl.lang.owl2.LiteralExpression expression) throws xowl.interpreter.XOWLException { return parent.toLiteral(eval_QueryVariable((xowl.lang.actions.QueryVariable)expression)); }
    @Override public xowl.lang.runtime.Function evalFunction(xowl.interpreter.impl.Evaluator parent, xowl.lang.actions.FunctionExpression expression) throws xowl.interpreter.XOWLException { return parent.toFunction(eval_QueryVariable((xowl.lang.actions.QueryVariable)expression)); }
    @Override public xowl.lang.runtime.Closure evalClosure(xowl.interpreter.impl.Evaluator parent, xowl.lang.actions.ExecutableExpression expression) throws xowl.interpreter.XOWLException { return parent.toClosure(eval_QueryVariable((xowl.lang.actions.QueryVariable)expression)); }
    @Override public xowl.lang.runtime.Array evalArray(xowl.interpreter.impl.Evaluator parent, xowl.lang.actions.ArrayExpression expression) throws xowl.interpreter.XOWLException { return parent.toArray(eval_QueryVariable((xowl.lang.actions.QueryVariable)expression)); }
    @Override public xowl.lang.runtime.JavaObject evalJavaObject(xowl.interpreter.impl.Evaluator parent, xowl.lang.interop.JavaObjectExpression expression) throws xowl.interpreter.XOWLException { return null; }

    @Override public List<xowl.interpreter.QuerySolution> select(xowl.interpreter.impl.Evaluator parent, xowl.lang.actions.Select query) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }

    @Override public xowl.lang.runtime.Entity toEntity(xowl.lang.runtime.Value value) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override public xowl.lang.runtime.Class toClass(xowl.lang.runtime.Value value) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override public xowl.lang.runtime.ObjectProperty toObjProp(xowl.lang.runtime.Value value) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override public xowl.lang.runtime.DataProperty toDataProp(xowl.lang.runtime.Value value) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override public xowl.lang.runtime.Datatype toDatatype(xowl.lang.runtime.Value value) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override public xowl.lang.runtime.Individual toIndividual(xowl.lang.runtime.Value value) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override public xowl.lang.runtime.Literal toLiteral(xowl.lang.runtime.Value value) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override public xowl.lang.runtime.Function toFunction(xowl.lang.runtime.Value value) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override public xowl.lang.runtime.Closure toClosure(xowl.lang.runtime.Value value) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override public xowl.lang.runtime.Array toArray(xowl.lang.runtime.Value value) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override public xowl.lang.runtime.JavaObject toJavaObject(xowl.lang.runtime.Value value) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }

    protected xowl.interpreter.XOWLException getNotImplemented() {
        return new xowl.interpreter.XOWLException("Not implemented");
    }
}
